/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef KH_SLE_SSAP_CLIENT_H
#define KH_SLE_SSAP_CLIENT_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdlib.h>
#include "sle_error_code.h"
#include "sle_ssap_config.h"
#include "sle_ssap_client_config.h"

/**
 * @brief  Find SsapStructure result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] service -structure of service
 * @param [in] errCode -find result code
 * @return none
 */
typedef void (*SleFindStructureCallback)(uint8_t clientId, uint16_t connectId
        , const ClientFindServiceRes *service, SleErrorCode errCode);

/**
 * @brief Find SsapProperty result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] property -property of service
 * @param [in] errCode -find result code
 * @return none
 */
typedef void (*SleFindPropertyCallback)(uint8_t clientId, uint16_t connectId
        , const ClientFindPropertyRes *property, SleErrorCode errCode);

/**
 * @brief Read SsapProperty result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] readData -read data
 * @param [in] errCode -read result code
 * @return none
 */
typedef void (*SleReadConformCallback)(uint8_t clientId, uint16_t connectId
        , const ClientHandleValue *readData, SleErrorCode errCode);

/**
 * @brief Write SsapProperty result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] writeResult -write result
 * @param [in] errCode -write result code
 * @return none
 */
typedef void (*SleWriteConformCallback)(uint8_t clientId, uint16_t connectId
        , const ClientWriteRes *writeResult, SleErrorCode errCode);

/**
 * @brief Exchange SsapProperty result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] exchangeInfo -exchangeInfo
 * @param [in] errCode -exchange result code
 * @return none
 */
typedef void (*SleExchangeInfoCallback)(uint8_t clientId, uint16_t connectId
        , const SsapMtuInfo *exchangeInfo, SleErrorCode errCode);

/**
 * @brief SsapNotification result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] data -notification data
 * @param [in] errCode -notification result code
 * @return none
 */
typedef void (*SleNotificatedCallback)(uint8_t clientId, uint16_t connectId
        , const ClientHandleValue *data, SleErrorCode errCode);

/**
 * @brief SsapIndication result callback
 *
 * @param [in] clientId -client id
 * @param [in] connectId -connection id
 * @param [in] data -indication data
 * @param [in] errCode -indication result code
 * @return none
 */
typedef void (*SleIndicatedCallback)(uint8_t clientId, uint16_t connectId
        , const ClientHandleValue *data, SleErrorCode errCode);

typedef struct {
    SleFindStructureCallback            OnSleFindStructureCb;
    SleFindPropertyCallback             OnSleFindPropertyCb;
    SleReadConformCallback              OnSleReadCfmCb;
    SleWriteConformCallback             OnSleWriteCfmCb;
    SleExchangeInfoCallback             OnSleExchangeInfoCb;
    SleNotificatedCallback              OnSleNotificatedCb;
    SleIndicatedCallback                OnSleIndicatedCb;
} SleSsapcCallbacks;

/**
 * @brief Init Ssapc Service
 *
 * @param none
 * @return SleErrorCode -result code
 */
SleErrorCode InitSleSsapcService(void);

/**
 * @brief Deinit Ssapc Service
 *
 * @param none
 * @return SleErrorCode -result code
 */
SleErrorCode DeinitSleSsapcService(void);

/**
 * @brief Add Ssapc Client
 *
 * @param [in] appUuid - uuid of application (invalid now, reserved for future use)
 * @param [out] clientId - client id will be given (invalid now, reserved for future use)
 * @return SleErrorCode -result code
 */
SleErrorCode AddSspaClient(const SleUuid* appUuid, uint8_t* clientId);

/**
 * @brief Remove Ssapc Client
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @return SleErrorCode -result code
 */
SleErrorCode RemoveClient(uint8_t clientId);

/**
 * @brief Find SsapStructure
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] paramFind -find structure parameter
 * @return SleErrorCode -result code
 *
 * @note result will be reported by callback function @link: SleFindStructureCallback/SleFindPropertyCallback
 */
SleErrorCode FindSsapStructure(uint8_t clientId, uint16_t connectId, const ClientFindStructure* paramFind);

/**
 * @brief Send ReadReqByUuid
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] paramRead -read request parameter
 * @return SleErrorCode -result code
 *
 * @note result will be reported by callback function @link: SleReadConformCallback
 */
SleErrorCode SendReadReqByUuid(uint8_t clientId, uint16_t connectId, const  ClientReadReqByUUID* paramRead);

/**
 * @brief Send ReadReq
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] handle -handle
 * @param [in] propertyTpye -property type
 * @return SleErrorCode -result code
 *
 * @note result will be reported by callback function @link: SleReadConformCallback
 */
SleErrorCode SendReadReq(uint8_t clientId, uint16_t connectId, uint16_t handle, SleSsapPropertyType propertyTpye);

/**
 * @brief Send WriteReq
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] paramWrite -write request parameter
 * @return SleErrorCode -result code
 *
 * @note result will be reported by callback function @link: SleWriteConformCallback
 *
 * TODO: 后续实现超时未收到则重传
 */
SleErrorCode SendWriteReq(uint8_t clientId, uint16_t connectId, const ClientWriteParam* paramWrite);

/**
 * @brief Send WriteCmd
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] paramWrite -write request parameter
 * @return SleErrorCode -result code
 *
 * @note result will not be reported
 */
SleErrorCode SendWriteCmd(uint8_t clientId, uint16_t connectId, const ClientWriteParam* paramWrite);

/**
 * @brief Send ExchangeInfoReq
 *
 * @param [in] clientId -client id (invalid now, reserved for future use)
 * @param [in] connectId -connection id
 * @param [in] paramExchange -exchange request parameter
 * @return SleErrorCode -result code
 *
 * @note result will be reported by callback function @link: SleExchangeInfoCallback
 */
SleErrorCode SendExchangeInfoReq(uint8_t clientId, uint16_t connectId, const SsapMtuInfo* paramExchange);

/**
 * @brief Register SsapClient Callbacks
 *
 * @param [in] ssapcCallbacks -callback function
 * @return SleErrorCode -result code
 *
 * @note client id will be given to client when register successfully
 */
SleErrorCode RegisterSsapClientCallbacks(SleSsapcCallbacks* ssapcCallbacks);

/**
 * @brief Unregister SsapClient Callbacks
 *
 * @param [in] ssapcCallbacks -callback functions
 * @return SleErrorCode -result code
 *
 * @note
 */
SleErrorCode UnregisterSsapClientCallbacks(SleSsapcCallbacks* ssapcCallbacks);

#ifdef __cplusplus
}
#endif
#endif